package com.info33.platform.doc.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.info33.platform.common.constant.CustomizeYaml;
import com.info33.platform.common.constant.TableConstant;
import com.info33.platform.common.enums.FileSuffixEnum;
import com.info33.platform.common.mvc.vo.Result;
import com.info33.platform.doc.dao.DocFileDao;
import com.info33.platform.doc.dao.DocFileDirectoryDao;
import com.info33.platform.doc.dto.DocFileDirectoryDTO;
import com.info33.platform.doc.entity.DocFile;
import com.info33.platform.doc.entity.DocFileDirectory;
import com.info33.platform.doc.service.DocFileDirectoryService;
import com.info33.platform.doc.util.enums.DocSpaceTypeEnum;
import com.info33.platform.doc.vo.DocFileDirectoryVO;
import com.info33.platform.system.vo.SysUserVO;

/**
 * @author admin
 */
@Service
@Transactional(rollbackFor = {Exception.class, Error.class})
public class DocFileDirectoryServiceImpl extends ServiceImpl<DocFileDirectoryDao, DocFileDirectory> implements DocFileDirectoryService {

    @Autowired
    private DocFileDirectoryDao docFileDirectoryDao;
    
    @Autowired
    private DocFileDao docFileDao;
    
    @Autowired
    private CustomizeYaml customizeYaml;

	@Override
	public List<DocFileDirectoryVO> getDirectoryTree(SysUserVO currentUser, String type) {
		return directoryTree(docFileDirectoryDao.selectListByParam(currentUser, type),0L);
	}
	
	public List<DocFileDirectoryVO> directoryTree(List<DocFileDirectoryVO> dirVOList, Long pid) {
        List<DocFileDirectoryVO> collect = dirVOList.stream().filter(l -> l.getPid().equals(pid)).collect(Collectors.toList());
        collect.forEach(l -> l.setChildren(directoryTree(dirVOList, l.getId())));
        return collect;
    }

	@Override
	public Result<?> saveFileDirectory(SysUserVO sysUserVO, DocFileDirectoryDTO docFileDirectoryDTO) {
		/*
		 * 1.目录是否存在 - BUSINESS: 全局唯一，其它同一级别唯一
		 * 2.服务器创建目录
		 * 3.存目录
		 */
		DocFileDirectory docFileDirectory = null;
		if(DocSpaceTypeEnum.BUSINESS.equals(docFileDirectoryDTO.getType())) {
			docFileDirectory = docFileDirectoryDao.selectOne(new QueryWrapper<DocFileDirectory>().eq("name", docFileDirectoryDTO.getName()));
		} else {
			docFileDirectory = docFileDirectoryDao.selectOne(new QueryWrapper<DocFileDirectory>()
					.eq(TableConstant.PID, docFileDirectoryDTO.getPid()).eq("name", docFileDirectoryDTO.getName()));
		}
		
		if(!ObjectUtils.isEmpty(docFileDirectory)) {
			return Result.error("此目录已存在");
		}
		//获取父级目录
		String parentDirectory = customizeYaml.getUploadPath() +  FileSuffixEnum.SLASH + "assets" + FileSuffixEnum.SLASH + docFileDirectoryDTO.getType();
		if(0 == docFileDirectoryDTO.getPid()) {
			parentDirectory += FileSuffixEnum.SLASH + docFileDirectoryDTO.getName();
		} else {
			List<DocFileDirectory> fileDirectoryList = docFileDirectoryDao.selectList(new QueryWrapper<DocFileDirectory>()
					.eq(TableConstant.TENANT_ID, sysUserVO.getTenant().getId()).eq("type", docFileDirectoryDTO.getType()));
			List<String> parentName = queryParentDirectory(docFileDirectoryDTO.getPid(), fileDirectoryList);
			for(int i = parentName.size() - 1; i >= 0; i -- ) {
				parentDirectory += FileSuffixEnum.SLASH + parentName.get(i);
			}
			parentDirectory += FileSuffixEnum.SLASH +docFileDirectoryDTO.getName();
		}
		File dirCheck = new File(parentDirectory);
		
		if (!dirCheck.exists()) {
			if(!dirCheck.mkdirs()) {
				return Result.error();
			}
		}
		docFileDirectory = new DocFileDirectory();
		BeanUtils.copyProperties(docFileDirectoryDTO, docFileDirectory);
		return docFileDirectoryDao.insert(docFileDirectory) > 0 ? Result.ok() : Result.error();
	}
	
	@Override
	public List<String> queryParentDirectory(Long id, List<DocFileDirectory> fileDirectoryList) {
		//递归获取父级名称,不包含自己
		List<String> parenNames = new ArrayList<String>();
        this.getParentNames(fileDirectoryList, id, parenNames);
        return parenNames;
    }
 
    private void getParentNames(List<DocFileDirectory> fileDirectoryList, Long id, List<String> parenNames) {
        for (DocFileDirectory fileDirectory : fileDirectoryList) {
            //判断是否有父节点
            if (id.equals(fileDirectory.getId())) {
            	parenNames.add(fileDirectory.getName());
            	getParentNames(fileDirectoryList, fileDirectory.getPid(), parenNames);
            }
        }
    }

	@Override
	public Result<?> editFileDirectory(SysUserVO sysUserVO, DocFileDirectoryDTO docFileDirectoryDTO) {
		DocFileDirectory docFileDirectory = null;
		if(DocSpaceTypeEnum.BUSINESS.equals(docFileDirectoryDTO.getType())) {
			docFileDirectory = docFileDirectoryDao.selectOne(new QueryWrapper<DocFileDirectory>()
					.eq("name", docFileDirectoryDTO.getName())
					.ne(TableConstant.ID, docFileDirectoryDTO.getId()));
		} else {
			docFileDirectory = docFileDirectoryDao.selectOne(new QueryWrapper<DocFileDirectory>()
					.eq(TableConstant.PID, docFileDirectoryDTO.getPid()).eq("name", docFileDirectoryDTO.getName())
					.ne(TableConstant.ID, docFileDirectoryDTO.getId()));
		}
		
		if(!ObjectUtils.isEmpty(docFileDirectory)) {
			return Result.error("此目录已存在");
		}
		docFileDirectory = docFileDirectoryDao.selectById(docFileDirectoryDTO.getId());
		if(ObjectUtils.isEmpty(docFileDirectory)) {
			return Result.error("此条目录不存在");
		}
	
		String newDirectory = customizeYaml.getUploadPath() + FileSuffixEnum.SLASH + "assets" + FileSuffixEnum.SLASH + docFileDirectoryDTO.getType();
		String oldDirectory = customizeYaml.getUploadPath() + FileSuffixEnum.SLASH + "assets" + FileSuffixEnum.SLASH + docFileDirectoryDTO.getType();
		if(0 == docFileDirectoryDTO.getPid()) {
			newDirectory += FileSuffixEnum.SLASH + docFileDirectoryDTO.getName();
			oldDirectory += FileSuffixEnum.SLASH + docFileDirectory.getName();
		} else {
			//获取父级目录
			List<DocFileDirectory> fileDirectoryList = docFileDirectoryDao.selectList(new QueryWrapper<DocFileDirectory>()
					.eq(TableConstant.TENANT_ID, sysUserVO.getTenant().getId()).eq("type", docFileDirectoryDTO.getType()));
			List<String> parentName = queryParentDirectory(docFileDirectoryDTO.getPid(), fileDirectoryList);
			for(int i = parentName.size() - 1; i >= 0; i -- ) {
				newDirectory += FileSuffixEnum.SLASH + parentName.get(i);
				oldDirectory += FileSuffixEnum.SLASH + parentName.get(i);
			}
			newDirectory += FileSuffixEnum.SLASH +docFileDirectoryDTO.getName();
			oldDirectory += FileSuffixEnum.SLASH +docFileDirectory.getName();
		}
		File oldDir = new File(oldDirectory);
		File newDir = new File(newDirectory);
		//重命名
		oldDir.renameTo(newDir);
		
		docFileDirectory = new DocFileDirectory();
		BeanUtils.copyProperties(docFileDirectoryDTO, docFileDirectory);
		return docFileDirectoryDao.updateById(docFileDirectory) > 0 ? Result.ok() : Result.error();
	}

	@Override
	public Result<?> removeFileDirectory(SysUserVO sysUserVO, Long id) {
		DocFileDirectory docFileDirectory = docFileDirectoryDao.selectById(id);
		if(ObjectUtils.isEmpty(docFileDirectory)) {
			return Result.error("此条目录不存在");
		}
		//有子目录的不能删除
		List<DocFileDirectory> sonDirectoryList = docFileDirectoryDao.selectList(new QueryWrapper<DocFileDirectory>()
				.eq(TableConstant.PID, id));
		if(!CollectionUtils.isEmpty(sonDirectoryList)) {
			return Result.error("此目录存在子目录，不能删除");
		}
		//有文档的不能删除
		List<DocFile> fileList = docFileDao.selectList(new QueryWrapper<DocFile>().eq("file_directory_id", id));
		if(!CollectionUtils.isEmpty(fileList)) {
			return Result.error("此目录存在文档，不能删除");
		}
		
		String deleteDirectory = customizeYaml.getUploadPath() + FileSuffixEnum.SLASH + "assets" + FileSuffixEnum.SLASH + docFileDirectory.getType();
		if(0 == docFileDirectory.getPid()) {
			deleteDirectory += FileSuffixEnum.SLASH + docFileDirectory.getName();
		} else {
			//获取父级目录
			List<DocFileDirectory> fileDirectoryList = docFileDirectoryDao.selectList(new QueryWrapper<DocFileDirectory>()
					.eq(TableConstant.TENANT_ID, sysUserVO.getTenant().getId()).eq("type", docFileDirectory.getType()));
			List<String> parentName = queryParentDirectory(docFileDirectory.getPid(), fileDirectoryList);
			for(int i = parentName.size() - 1; i >= 0; i -- ) {
				deleteDirectory += FileSuffixEnum.SLASH + parentName.get(i);
			}
			deleteDirectory += FileSuffixEnum.SLASH + docFileDirectory.getName();
		}
		if(new File(deleteDirectory).delete()) {
			return docFileDirectoryDao.deleteById(id) > 0 ? Result.ok() : Result.error();
		}
		return Result.error();
	}

}